﻿using Com.Lancetinc.Evs.Data;
using Com.Lancetinc.Evs.Data.Domain;
using Com.Lancetinc.Evs.Events;
using Com.Lancetinc.Evs.Helpers;
using Com.Lancetinc.Evs.Services;
using Com.Lancetinc.Evs.ViewModels;
using Com.Lancetinc.Evs.Windows;
using MahApps.Metro.Controls;
using NLog;
using Prism.Events;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.ComponentModel.Composition.Primitives;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using static Com.Lancetinc.Evs.Services.ExperBackupService;
using Cursors = System.Windows.Input.Cursors;
using DataGrid = System.Windows.Controls.DataGrid;

namespace Com.Lancetinc.Evs.Controls
{
    /// <summary>
    /// HistoryPageUserControl.xaml 的交互逻辑
    /// </summary>
    public partial class HistoryPageUserControl
    {
        private static readonly ILogger Logger = LogManager.GetCurrentClassLogger();

        private IList<ExperViewModel> _experList;

        public HistoryPageUserControl()
        {
            InitializeComponent();
            PanelNavButtons.DataContext = this;
            this.Loaded += HistoryPageUserControl_Loaded;
        }

        private void HistoryPageUserControl_Loaded(object sender, RoutedEventArgs e)
        {
            KnownAppEvents.ComboBoxAutoCompleteItemsChangedEvent.Subscribe(ComboBoxItemsChanged, ThreadOption.UIThread);
        }

        private void ButtonClear_Click(object sender, RoutedEventArgs e)
        {
            CtrlCond.ClearInputConds();
            // 清除排序条件
            MainGrid.Columns.Where(x => x.SortDirection != null).ToList().ForEach(x => x.SortDirection = null);
            MainGrid.Items.SortDescriptions.Clear();
            _sortingKey = null;

            Refresh();
        }

        private void ButtonSearch_Click(object sender, RoutedEventArgs e)
        {
            Refresh();
        }

        private void ComboBoxItemsChanged(ComboBoxAutoCompleteItemsChangedEventArgs obj)
        {
            CtrlCond.ReloadSelectItems();
        }

        public async void Refresh()
        {
            await SearchAsync();
        }

        #region 分页相关

        private const int PageSize = 20;
        private int _currentPageNo = 1;
        private PagingInfo<Exper> _pagingInfo;
        private SqlCondItem[] _currentConds;

        private async Task SearchAsync()
        {
            if (!await CtrlCond.ValidInput())
                return;

            using var _ = StartBusy();
            _pagingInfo = null;
            _currentConds = CtrlCond.GetInputConds();
            await FirstPage();
        }

        private async Task FirstPage()
        {
            await JumpToPage(1);
        }

        private async Task LastPage()
        {
            await JumpToPage(_pagingInfo.PageCount);
        }

        private async Task PreviousPage()
        {
            if (_currentPageNo <= 0)
                return; // 已经是第一页

            await JumpToPage(--_currentPageNo);
        }

        private async Task NextPage()
        {
            if (_pagingInfo == null)
                return;

            if (_currentPageNo >= _pagingInfo.PageCount)
                return; // 已经是最后一页

            await JumpToPage(++_currentPageNo);
        }

        private async Task JumpToPage(int pageNo)
        {
            var totalCount = _pagingInfo?.TotalCount ?? -1;
            _pagingInfo = await Task.Factory.StartNew(() =>
                AppRepositories.Exper.QueryPage(_currentConds, pageNo, PageSize, totalCount, GetOrderByClause()));
            _currentPageNo = pageNo;
            if (_experList == null)
            {
                _experList = new ObservableCollection<ExperViewModel>();
                MainGrid.DataContext = _experList;
            }
            else
            {
                _experList.Clear();
            }

            foreach (var exper in _pagingInfo.List)
            {
                _experList.Add(new ExperViewModel(exper));
            }
            if (_experList.Count > 0)
            {
                MainGrid.ScrollIntoView(_experList.First());
            }

            RefreshPagination(_pagingInfo, pageNo);
        }

        #endregion

        private IDisposable StartBusy()
        {
            this.PanelSearch.IsEnabled = false;
            Mouse.OverrideCursor = Cursors.Wait;
            return new DelegateDisposable(() =>
            {
                Mouse.OverrideCursor = null;
                this.PanelSearch.IsEnabled = true;
            });
        }

        private void MainGrid_OnMouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            if (!(e.OriginalSource is FrameworkElement ele))
            {
                return;
            }

            var row = WpfHelper.FindVisualParent<DataGridRow>(ele);
            if (row == null)
                return;

            var experVm = row.DataContext as ExperViewModel;
            if (experVm == null) return;

            WpfHelper.ExecLater(() => { ShowExperDetailWindow(experVm); }, 100);
        }

        private void BtnPlay_OnClick(object sender, RoutedEventArgs e)
        {
            var expVm = (sender as FrameworkElement).Tag as ExperViewModel;
            if (expVm == null) return;

            ShowExperDetailWindow(expVm);
        }

        private void ShowExperDetailWindow(ExperViewModel experVm)
        {
            ExperDetailWindow.Show(experVm);

            if (experVm.SeqNo == null && _experList != null)
            {
                // 被删除了
                _experList.Remove(experVm);
            }
        }

        private void BtnReport_OnClick(object sender, RoutedEventArgs e)
        {
            var experVm = (sender as FrameworkElement)?.Tag as ExperViewModel;
            if (experVm == null) return;

            ReportEditWindow.Show(experVm);

            if (experVm.SeqNo == null && _experList != null)
            {
                // 被删除了
                _experList.Remove(experVm);
            }
        }

        /// <summary>
        /// 当前页改变
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="pageNo"></param>
        private async void CtrlPagination_OnCurrentPageChanged(object sender, int pageNo)
        {
            if (_currentPageNo == pageNo) return;
            await JumpToPage(pageNo);
        }

        private void RefreshPagination(PagingInfo<Exper> pagingInfo, int pageNo)
        {
            CtrlPagination.TotalCount = pagingInfo.TotalCount;
            CtrlPagination.PageSize = pagingInfo.PageSize;
            CtrlPagination.CurrentPageNo = pageNo;
        }

        private void BtnBack_OnClick(object sender, RoutedEventArgs e)
        {
            var flyout = this.Parent as Flyout;
            if (flyout == null) return;
            flyout.IsOpen = false;
        }

        #region Sorting

        private SortDescription? _sortingKey = null;

        private string GetOrderByClause()
        {
            if (_sortingKey == null)
                return null;
            var sk = _sortingKey.Value;
            var asc = _sortingKey.Value.Direction == ListSortDirection.Descending ? "desc" : "";
            return $"{sk.PropertyName} {asc}";
        }

        private void MainGrid_OnSorting(object sender, DataGridSortingEventArgs e)
        {
            e.Handled = true;
            var dataGrid = (DataGrid)sender;
            ListSortDirection? NextSortDirection()
            {
                if (!e.Column.SortDirection.HasValue)
                    return ListSortDirection.Ascending;
                if (e.Column.SortDirection.Value == ListSortDirection.Ascending)
                    return ListSortDirection.Descending;
                return null;
            }

            var sd = dataGrid.Items.SortDescriptions;
            var nextDir = NextSortDirection();
            // 原来的排序：点击一次升序，再点击一次降序，再点击升序。导致无法恢复到不排序的状态
            // 改成：降序之后点击一次变为不排序
            if (nextDir == null)
            {
                sd.Clear();
                e.Column.SortDirection = null;
                _sortingKey = null;
                Refresh();
                return;
            }

            sd.Clear();
            sd.Add(new SortDescription(e.Column.SortMemberPath, nextDir.Value));
            e.Column.SortDirection = nextDir;
            _sortingKey = new SortDescription(e.Column.SortMemberPath, nextDir.Value);
            Refresh();
        }

        #endregion

        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void BtnDelete_OnClick(object sender, RoutedEventArgs e)
        {
            var selectedRows = MainGrid.SelectedItems.OfType<ExperViewModel>().ToArray();
            if (selectedRows.Length == 0)
                return;

            var r = await MessageHelper.ShowYesNoByMsgIdAsync("ExperDetailWindow.ConfirmDeletePatientInfo", Msgs.MsgBox_DeleteConfirm);
            if (r != MessageBoxResult.Yes)
            {
                return;
            }

            int successCount = 0;
            foreach (var experVm in selectedRows)
            {
                try
                {
                    AppRepositories.Exper.DeleteBySeqNo(experVm.Exper.SeqNo);
                    successCount++;
                }
                catch (Exception ex)
                {
                    Logger.Error(ex);
                    MessageHelper.ShowError(ex.Message, Msgs.MsgBox_DeleteFailed);
                    break;
                }

                var mExper = ExperManager.Default.WrapHistoryExper(experVm);
                if (!Directory.Exists(mExper.WorkDir))
                    continue;

                try
                {
                    Directory.Delete(mExper.WorkDir, true);
                }
                catch (Exception ex)
                {
                    Logger.Error(ex);
                    MessageHelper.ShowWarning(I18nHelper.Default.GetMessageWithArgs("ExperDetailWindow.DeleteFolderFailed", mExper.WorkDir));
                    break;
                }
            }

            if (successCount > 0)
            {
                Refresh();
            }
        }

        /// <summary>
        /// 导入
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void BtnImport_OnClick(object sender, RoutedEventArgs e)
        {
            using var dialog = new System.Windows.Forms.OpenFileDialog
            {
                Multiselect = false,
                Title = I18nHelper.Default.GetMessage("HistoryPageUserControl.ImportDlgTitle"),
                Filter = I18nHelper.Default.GetMessage("HistoryPageUserControl.DbFilter")
            };
            if (dialog.ShowDialog() != System.Windows.Forms.DialogResult.OK)
                return;

            // 正在导出...
            var msg = I18nHelper.Default.GetMessage("HistoryPageUserControl.Importing");
            using var pdc = await WaitBoxHelper.WaitBox.ShowAsync("",
                msg, false, false);

            var service = new ExperBackupService();
            var sbError = new StringBuilder();
            var dbChanged = await service.ImportAsync(dialog.FileName, sbError);
            if (sbError.Length > 0)
            {
                MessageHelper.ShowError(sbError.ToString().TrimEnd());
            }

            if (dbChanged)
            {
                Refresh();
            }
        }

        /// <summary>
        /// 备份
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void BtnBackup_OnClick(object sender, RoutedEventArgs e)
        {
            var ext = I18nHelper.Default.GetMessage("HistoryPageUserControl.DbFileExt");
            using var dialog = new System.Windows.Forms.SaveFileDialog
            {
                FileName = DateTime.Now.ToString("yyyy_MMdd_HHmmss") + ext,
                Title = I18nHelper.Default.GetMessage("HistoryPageUserControl.ExportDlgTitle"),//导出数据库文件
                Filter = I18nHelper.Default.GetMessage("HistoryPageUserControl.DbFilter") //数据库文件|*.lzdb
            };

            if (dialog.ShowDialog() != System.Windows.Forms.DialogResult.OK)
                return;

            // 正在导出...
            var msg = I18nHelper.Default.GetMessage("HistoryPageUserControl.Exporting");
            using var pdc = await WaitBoxHelper.WaitBox.ShowAsync("",
                msg, true, true);

            var service = new ExperBackupService();
            var expers = AppRepositories.Exper.QueryPage(_currentConds, 1, 99999).List;
            var dbVersion = AppRepositories.Config.GetDbVersion();
            var progress = new BackupProgress(p =>
            {
                pdc.Progress = (int)(p * 100);
            });

            var cts = new CancellationTokenSource();
            pdc.OnDisposed += (_, _) => { cts.Cancel(); };
            await service.ExportAsync(dialog.FileName, expers.ToArray(), dbVersion, progress, cts.Token);
        }
    }
}
